import { EventEmitter } from '../utils/EventEmitter';
import { Collider, CollisionResult, CollisionEventType } from './types';
import { Logger } from '../utils/Logger';

/**
 * 碰撞管理器类
 */
export class CollisionManager extends EventEmitter {
    private colliders: Set<Collider> = new Set();
    private collisionPairs: Map<string, boolean> = new Map();
    private logger: Logger;
    
    constructor() {
        super();
        this.logger = new Logger();
    }
    
    /**
     * 添加碰撞体
     */
    public addCollider(collider: Collider): void {
        if (this.colliders.has(collider)) {
            this.logger.warn('Collider already exists');
            return;
        }
        
        this.colliders.add(collider);
        this.logger.debug('Collider added:', collider);
    }
    
    /**
     * 移除碰撞体
     */
    public removeCollider(collider: Collider): void {
        if (!this.colliders.has(collider)) {
            this.logger.warn('Collider does not exist');
            return;
        }
        
        // 移除与该碰撞体相关的所有碰撞对
        for (const pair of this.collisionPairs.keys()) {
            const [id1, id2] = pair.split(':');
            if (id1 === collider.id || id2 === collider.id) {
                this.collisionPairs.delete(pair);
            }
        }
        
        this.colliders.delete(collider);
        this.logger.debug('Collider removed:', collider);
    }
    
    /**
     * 更新碰撞检测
     */
    public update(deltaTime: number): void {
        // 检查所有碰撞体对
        const colliders = Array.from(this.colliders);
        for (let i = 0; i < colliders.length; i++) {
            const colliderA = colliders[i];
            if (!colliderA.enabled) continue;
            
            for (let j = i + 1; j < colliders.length; j++) {
                const colliderB = colliders[j];
                if (!colliderB.enabled) continue;
                
                // 检查碰撞层是否匹配
                if (!this.canCollide(colliderA, colliderB)) continue;
                
                // 检查是否已经碰撞
                const pairKey = this.getPairKey(colliderA, colliderB);
                const wasColliding = this.collisionPairs.get(pairKey) || false;
                
                // 检测碰撞
                const result = this.checkCollision(colliderA, colliderB);
                
                // 处理碰撞事件
                if (result.collided) {
                    if (!wasColliding) {
                        // 碰撞开始
                        this.collisionPairs.set(pairKey, true);
                        this.emitCollisionEvent(CollisionEventType.COLLISION_START, colliderA, colliderB, result);
                    } else {
                        // 碰撞持续
                        this.emitCollisionEvent(CollisionEventType.COLLISION_STAY, colliderA, colliderB, result);
                    }
                } else if (wasColliding) {
                    // 碰撞结束
                    this.collisionPairs.delete(pairKey);
                    this.emitCollisionEvent(CollisionEventType.COLLISION_END, colliderA, colliderB, result);
                }
            }
        }
    }
    
    /**
     * 检查两个碰撞体是否可以碰撞
     */
    private canCollide(a: Collider, b: Collider): boolean {
        // 检查碰撞层
        if ((a.layer & b.layer) === 0) {
            return false;
        }
        
        // 检查碰撞标签
        if (a.tag === b.tag) {
            return false;
        }
        
        return true;
    }
    
    /**
     * 检查两个碰撞体之间的碰撞
     */
    private checkCollision(a: Collider, b: Collider): CollisionResult {
        // 使用AABB进行快速碰撞检测
        if (!this.checkAABB(a, b)) {
            return { collided: false };
        }
        
        // 进行精确碰撞检测
        return a.calculateCollision(b);
    }
    
    /**
     * 使用AABB进行快速碰撞检测
     */
    private checkAABB(a: Collider, b: Collider): boolean {
        const aMin = a.bounds.min;
        const aMax = a.bounds.max;
        const bMin = b.bounds.min;
        const bMax = b.bounds.max;
        
        return (
            aMin.x <= bMax.x &&
            aMax.x >= bMin.x &&
            aMin.y <= bMax.y &&
            aMax.y >= bMin.y
        );
    }
    
    /**
     * 获取碰撞对的唯一键
     */
    private getPairKey(a: Collider, b: Collider): string {
        // 确保较小的ID在前，以保持一致性
        return a.id < b.id ? `${a.id}:${b.id}` : `${b.id}:${a.id}`;
    }
    
    /**
     * 触发碰撞事件
     */
    private emitCollisionEvent(
        type: CollisionEventType,
        a: Collider,
        b: Collider,
        result: CollisionResult
    ): void {
        const event = {
            type,
            colliderA: a,
            colliderB: b,
            result
        };
        
        // 触发全局碰撞事件
        this.emit(type, event);
        
        // 触发碰撞体上的事件
        a.emit(type, event);
        b.emit(type, event);
        
        // 如果是触发器，触发触发器事件
        if (a.isTrigger || b.isTrigger) {
            const triggerType = type.replace('COLLISION', 'TRIGGER') as CollisionEventType;
            this.emit(triggerType, event);
            a.emit(triggerType, event);
            b.emit(triggerType, event);
        }
    }
    
    /**
     * 销毁碰撞管理器
     */
    public destroy(): void {
        this.colliders.clear();
        this.collisionPairs.clear();
        this.removeAllListeners();
        this.logger.info('Collision manager destroyed');
    }
} 